package order

import (
	"awesomeProject/order-web/api"
	"awesomeProject/order-web/forms"
	"awesomeProject/order-web/global"
	"awesomeProject/order-web/models"
	"awesomeProject/order-web/proto"
	"context"
	"github.com/gin-gonic/gin"
	"github.com/smartwalle/alipay/v3"
	"go.uber.org/zap"
	"net/http"
	"strconv"
)

func List(ctx *gin.Context) {
	request := proto.OrderFilterRequest{}

	claims, _ := ctx.Get("claims") // 获取用户的权限
	model := claims.(*models.CustomClaims)

	if model.AuthorityId != 2 { // 不为管理员，只能获得当前用户对应的订单内容
		userId, _ := ctx.Get("userId")
		zap.S().Infof("userId: %v", userId)
		request.UserId = int32(userId.(uint))
	}
	pages := ctx.DefaultQuery("p", "0") // p为前后端约定字段---分页
	pagesInt, _ := strconv.Atoi(pages)
	request.Pages = int32(pagesInt)

	pageNum := ctx.DefaultQuery("pnum", "0") // pnum为前后端约定字段---页码
	pageNumInt, _ := strconv.Atoi(pageNum)
	request.PagePerNums = int32(pageNumInt)

	rsp, err := global.OrderSrvClient.OrderList(context.WithValue(context.Background(), "ginContext", ctx), &request)
	if err != nil {
		zap.S().Errorw("获取订单列表失败")
		api.HandleGrpcErrorToHttp(err, ctx)
		return
	}

	rspMap := make(map[string]interface{})
	rspMap["total"] = rsp.Total

	orderList := make([]interface{}, 0)
	for _, data := range rsp.Data {
		orderInfo := make(map[string]interface{})
		orderInfo["id"] = data.Id
		orderInfo["user"] = data.UserId
		orderInfo["name"] = data.Name
		orderInfo["status"] = data.Status
		orderInfo["pay_type"] = data.PayType
		orderInfo["mobile"] = data.Mobile
		orderInfo["address"] = data.Address
		orderInfo["total"] = data.Total
		orderInfo["post"] = data.Post
		orderInfo["order_sn"] = data.OrderSn
		orderInfo["add_time"] = data.AddTime
		orderList = append(orderList, orderInfo)
	}

	rspMap["data"] = orderList

	ctx.JSON(http.StatusOK, rspMap)
}

func New(ctx *gin.Context) {

	orderForm := forms.CreateOrderForm{}
	if err := ctx.ShouldBind(&orderForm); err != nil {
		api.HandleValidateError(err, ctx)
		return
	}
	userId, _ := ctx.Get("userId")

	rsp, err := global.OrderSrvClient.CreateOrder(context.WithValue(context.Background(), "ginContext", ctx), &proto.OrderRequest{
		UserId:  int32(userId.(uint)),
		Name:    orderForm.Name,
		Address: orderForm.Address,
		Mobile:  orderForm.Mobile,
		Post:    orderForm.Post,
	})

	if err != nil {
		zap.S().Errorw("创建订单失败")
		api.HandleGrpcErrorToHttp(err, ctx)
		return
	}

	// 订单创建后需要返回支付宝的url，供给进行支付，然后修改状态
	alipayUrl, err := AliPayFuncDebug(rsp.Total, rsp.OrderSn)
	if err != nil {
		zap.S().Errorw("获取支付宝URL服务失败")
		api.HandleGrpcErrorToHttp(err, ctx)
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"order_id":   rsp.Id,
		"alipay_url": alipayUrl,
	})

}
func Detail(ctx *gin.Context) {

	orderIdStr := ctx.Param("id")
	orderId, err := strconv.ParseInt(orderIdStr, 10, 32)
	// 不是数字字符串
	if err != nil {
		ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
			"msg": "url对应的id字符串无法解析为int",
		})
		return
	}

	// 如果为管理员就不设置UserId
	request := proto.OrderRequest{
		Id: int32(orderId),
	}

	claims, _ := ctx.Get("claims") // 获取用户的权限
	model := claims.(*models.CustomClaims)

	if model.AuthorityId != 2 { // 不为管理员，只能获得当前用户对应的订单内容
		userId, _ := ctx.Get("userId")
		request.UserId = userId.(int32)
	}

	rsp, err := global.OrderSrvClient.OrderDetail(context.Background(), &request)
	if err != nil {
		zap.S().Error("获取订单详细信息失败")
		api.HandleGrpcErrorToHttp(err, ctx)
		return
	}
	rspMap := make(map[string]interface{})
	// 维护订单信息
	rspMap["id"] = rsp.OrderInfo.Id
	rspMap["user"] = rsp.OrderInfo.UserId
	rspMap["name"] = rsp.OrderInfo.Name
	rspMap["status"] = rsp.OrderInfo.Status
	rspMap["pay_type"] = rsp.OrderInfo.PayType
	rspMap["mobile"] = rsp.OrderInfo.Mobile
	rspMap["address"] = rsp.OrderInfo.Address
	rspMap["total"] = rsp.OrderInfo.Total
	rspMap["post"] = rsp.OrderInfo.Post
	rspMap["order_sn"] = rsp.OrderInfo.OrderSn
	rspMap["add_time"] = rsp.OrderInfo.AddTime

	goodList := make([]interface{}, 0)
	for _, good := range rsp.Goods {

		goodInfo := make(map[string]interface{})
		goodInfo["id"] = good.Id
		goodInfo["good_name"] = good.GoodsName
		goodInfo["good_image"] = good.GoodsImage
		goodInfo["good_price"] = good.GoodsPrice
		goodInfo["nums"] = good.Nums
		goodList = append(goodList, goodInfo)
	}
	rspMap["goods"] = goodList

	// 获取订单详情时，订单可能创建了但是未支付，所以需要返回url，但是这里的具体实现逻辑要不要查询订单是否是未支付？？？
	alipayUrl, err := AliPayFuncDebug(rsp.OrderInfo.Total, rsp.OrderInfo.OrderSn)
	if err != nil {
		zap.S().Errorw("获取支付宝URL服务失败")
		api.HandleGrpcErrorToHttp(err, ctx)
		return
	}

	rspMap["alipay_url"] = alipayUrl

	ctx.JSON(http.StatusOK, rspMap)
}

func AliPayFuncDebug(orderTotal float32, orderSn string) (string, error) {

	appid := global.ServerConfig.AlipayInfo.AppID
	appPrivateKey := global.ServerConfig.AlipayInfo.AppPrivateKey
	alipayPublicKey := global.ServerConfig.AlipayInfo.AliPayPublicKey

	client, err := alipay.New(appid, appPrivateKey, false) // false表示测试环境
	if err != nil {
		zap.S().Info("创建支付宝支付客户端失败")
		return "", err
	}
	err = client.LoadAliPayPublicKey(alipayPublicKey)
	if err != nil {
		zap.S().Info("加载支付宝公钥失败")
		return "", err
	}

	pay := alipay.TradePagePay{}
	pay.NotifyURL = global.ServerConfig.AlipayInfo.NotifyURL
	pay.ReturnURL = global.ServerConfig.AlipayInfo.ReturnURL
	pay.Subject = "订单支付-" + orderSn
	pay.OutTradeNo = orderSn // 给支付宝维护
	pay.TotalAmount = strconv.FormatFloat(float64(orderTotal), 'f', 2, 64)
	pay.ProductCode = "FAST_INSTANT_TRADE_PAY"

	payUrl, err := client.TradePagePay(pay)
	if err != nil {
		zap.S().Info("生成支付url失败")
		return "", err
	}

	return payUrl.String(), nil
}
